package netty.rpc.client;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import netty.rpc.server.RpcResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * NettyRpc 客户端核心处理器
 * @author Jim
 * @version 1.0.0
 * @descripition:
 * @date 2022/5/14 16:18
 */
public class NettyRpcClientHandler extends ChannelInboundHandlerAdapter {

    private static final Logger logger = LogManager.getLogger(NettyRpcClientHandler.class);

    private  Map<String, RpcResponse> responses = new ConcurrentHashMap<>();

    private static final Long SLEEP_INTERVAL = 5L;

    private Long timeOut;

    public NettyRpcClientHandler(Long timeOut) {
        this.timeOut = timeOut;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        RpcResponse response = (RpcResponse) msg;
        if (!response.getTimeout()){
            responses.put(response.getRequestId(), response);
        }
        logger.debug( "requestId "+response.getRequestId()+"timeOut response= "+response);
    }


    public RpcResponse getResponse(String requestId) {
        long waitTime = System.currentTimeMillis();
        RpcResponse response = new RpcResponse();
        while (responses.get(requestId) == null){
            logger.debug(System.currentTimeMillis()+": requestId: " + requestId + " response is null");
            if (System.currentTimeMillis()  > timeOut + waitTime){
                logger.debug(System.currentTimeMillis()+" > " + timeOut + waitTime+" time out.");
                break;
            }
            try {
                Thread.sleep(SLEEP_INTERVAL);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        response = responses.get(requestId);
        if (response == null){
            response = new RpcResponse();
            response.setSuccess(RpcResponse.FAILURE);
            response.setTimeout(true);
        }else {
            response.setSuccess(RpcResponse.SUCCESS);
        }
        responses.remove(requestId);
        return response;
    }
}
